from datetime import datetime
from functools import reduce
from pathlib import Path
from typing import Any

import pandas as pd
from PyQt6.QtWidgets import QFileDialog
from pandas._typing import MergeHow
from qfluentwidgets import BodyLabel, FluentIcon as FIF, setFont, PrimaryPushButton, SwitchButton, \
    GroupHeaderCardWidget, ComboBox, PushButton, IndicatorPosition, InfoBar

from common import Icon, OfficeIcon
from components import BaseScrollArea, FileListSettingCard


def file_to_pd(file: str) -> pd.DataFrame:
    file = Path(file)
    match file.suffix:
        case ".csv":
            return pd.read_csv(file)
        case ".xlsx" | ".xls":
            return pd.read_excel(file)
        case ".json":
            return pd.read_json(file)
        case _:
            raise ValueError(f"Unsupported file type: {file.suffix}")


def merge_excel(
        files: list,
        output: str,
        how: MergeHow = 'outer',
        on=None,
        sort=False
):
    dataframes = [file_to_pd(file) for file in files]
    merged_df = reduce(
        lambda
            left, right:
        pd.merge(
            left, right,
            how=how,
            on=on,
            sort=sort
        ),
        dataframes
    )

    merged_df.to_excel(output, index=False)


class ExcelMergeView(BaseScrollArea):
    title = 'Excel 合并'
    description = '将多个 Excel 文件合并为一个文件'
    icon = OfficeIcon.EXCEL5

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.titleLabel = BodyLabel(self.title, parent=self)
        self.fileListSettingCard = FileListSettingCard(
            Icon.EXCEL, "需要合并的文件",
            "格式：(*.xlsx *.xls *.csv *.json)",
            parent=self)
        self.headerCard = GroupHeaderCardWidget('基本配置', self)
        self.comboBox = ComboBox(self)
        self.onComboBox = ComboBox(self)
        self.sortSwitch = SwitchButton('否', parent=self, indicatorPos=IndicatorPosition.RIGHT)
        self.selectButton = PushButton(FIF.SAVE_AS, '选择文件', self)
        self.startButton = PrimaryPushButton(FIF.PLAY, '开始合并', self)

        self.__initWidgets()

    def __initWidgets(self):
        self.setReturnVisible(True)

        self.comboBox.addItems(["left", "right", "inner", "outer", "cross"])
        self.comboBox.setCurrentIndex(3)

        self.savePathGroup = self.headerCard.addGroup(FIF.SAVE, '保存文件路径', '选择 Excel 保存文件路径',
                                                      self.selectButton)
        self.headerCard.addGroup(FIF.MENU, '合并方式', '选择合并方式', self.comboBox)
        self.headerCard.addGroup(FIF.ACCEPT, 'Key 字段',
                                 '选择文件标题字段，用于合并，选中的文件必须都包含该字段', self.onComboBox)
        self.headerCard.addGroup(FIF.LEAF, '排序', '是否对合并后的文件进行排序', self.sortSwitch)
        self.headerCard.addGroup(FIF.PLAY, '开始合并', '开始多个 Excel 文件', self.startButton)

        setFont(self.titleLabel, 24)
        self.scrollLayout.setContentsMargins(36, 24, 36, 10)
        self.scrollLayout.addWidget(self.titleLabel)
        self.scrollLayout.addWidget(self.fileListSettingCard)
        self.scrollLayout.addWidget(self.headerCard)

        self.fileListSettingCard.fileChanged.connect(self.onFileListChanged)
        self.selectButton.clicked.connect(self.selectFile)
        self.startButton.clicked.connect(self.mergeExcel)
        self.sortSwitch.checkedChanged.connect(self.onSortChanged)

    def onSortChanged(self, isChecked):
        self.sortSwitch.setText('是' if isChecked else '否')

    def selectFile(self):
        t = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        file, _ = QFileDialog.getSaveFileName(self, "选择 Excel 文件", f"./output-{t}.xlsx",
                                              "Excel files (*.xlsx *.xls)")
        if file:
            self.savePathGroup.setContent(file)

    def mergeExcel(self):
        files = self.fileListSettingCard.files
        if not files:
            return
        self.load(merge_excel, files, self.savePathGroup.content(), self.comboBox.currentText(),
                  on=self.onComboBox.currentText(), sort=self.sortSwitch.isChecked())

    def onFileListChanged(self, files: list):
        columns = []
        for file in files:
            df = file_to_pd(file)
            columns.extend(df.columns)
        self.onComboBox.clear()
        self.onComboBox.addItems(list(set(columns)))

    def onFuncSuccess(self, result: Any):
        InfoBar.success('合并成功', f'合并成功，文件保存至 {self.savePathGroup.content()}', duration=3000, parent=self)


if __name__ == '__main__':
    merge_excel(
        [
            r"C:\Users\26406\Downloads\data3.xlsx",
            r"C:\Users\26406\Downloads\data2.xlsx",
            r"C:\Users\26406\Downloads\data1.xlsx"
        ],
        r"C:\Users\26406\Downloads\output.xlsx"
    )
